<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- 
      数据要响应式的化，在 data 选项中需要事先声明好，否则后续添加的属性是没有响应式的。
          Vue 在初始化的过程中，会获取到 data 选项的值（对象）循环这个对象，给每一个属性都做一遍 get 与 set
            Object.defineProperty(vm, 'a')
            Object.defineProperty(vm, 'person')
            Object.defineProperty(vm.person, 'name')
            Object.defineProperty(vm.person, 'age')

      如果我们就是需要在后续添加属性且需要响应要如何办呢？就要使用实例方法$set
      
      $set语法
        this.$set(target, prop, value)
        Vue.set(target, prop, value)

        实例对象上的$set指向的就是Vue原型对象上的set方法

      $delete语法
        this.$delete(target, prop)
        Vue.delete(target, prop)

      由于ES5中 Object.defineProperty 自身的局限性，无法监控数组数据的变化。为了解决这个问题，
        Vue2中，将数据常用的7个方法做了改写
          push
          unshift
          pop
          shift
          splice
          sort
          reverse
      但还有一些数组的操作不会引起页面的更新
        1. 直接以数据下标的方式该某一个项目时
          this.$set(target, index, value)
          Vue.set(target, index, value)
          
        2. 直接修改数组length属性时
          splice(length)

     -->

    <div id="app">
      <button>{{ a }}</button>
      <ul>
        <li v-for="(value, key, index) in person" :key="index">
          {{ key }} - {{ value }}
        </li>
      </ul>

      <button @click="fn1">添加一个 person.sex</button>
      <button @click="fn2">删除 person.age 属性</button>

      <hr />
      <ul>
        <li v-for="item in todos" :key="item">{{ item }}</li>
      </ul>

      <button @click="fn3">todos[0] = '痴迷练'</button>
      <button @click="fn4">todos.length = 1</button>
    </div>

    <script src="../lib/vue.js"></script>

    <script>
      const data = {
        a: 1,
        person: {
          name: "张三",
          age: 18,
        },
        todos: ["吃饭", "睡觉", "打豆豆"],
      };

      const vm = new Vue({
        el: "#app",
        data: data,
        methods: {
          fn1() {
            // this.person.sex = "男";
            // this.$set(this.person, "sex", "男");
            Vue.set(this.person, "sex", "男");

            console.log(this.person);
          },
          fn2() {
            // delete this.person.age;

            // this.$delete(this.person, "age");
            Vue.delete(this.person, "age");

            console.log(this.person);
          },
          fn3() {
            // this.todos[0] = "痴迷练";

            this.$set(this.todos, 0, "痴迷练");
            console.log(this.todos);
          },
          fn4() {
            // this.todos.length = 1;
            this.todos.splice(1);
          },
        },
      });
    </script>
  </body>
</html>
